﻿#include "SceneManager.h"
#include <iostream> // 用于基本日志记录/错误消息

namespace GameEngine {

SceneManager::SceneManager() : m_currentScene(nullptr) {}

SceneManager::~SceneManager() {
    UnloadAllScenes();
}

void SceneManager::SwitchToScene(const std::string& name) {
    if (m_currentSceneName == name && m_currentScene) {

        if (!m_currentScene->IsActive()) {
             m_currentScene->m_isActive = true;
             m_currentScene->OnActivate();
        }
        return;
    }
    if (m_currentScene) {
        m_currentScene->m_isActive = false;
        m_currentScene->OnDeactivate();
    }

    auto it_loaded = m_loadedScenes.find(name);
    if (it_loaded != m_loadedScenes.end()) {
        m_currentScene = it_loaded->second;
    } else {
        auto it_factory = m_sceneFactories.find(name);
        if (it_factory == m_sceneFactories.end()) {
            throw std::runtime_error("SceneManager: No scene factory registered for '" + name + "'");
        }
        m_currentScene = it_factory->second(); 
        if (!m_currentScene) {
             throw std::runtime_error("SceneManager: Factory for '" + name + "' returned nullptr.");
        }
        m_loadedScenes[name] = m_currentScene;
    }
    
    m_currentSceneName = name;

    if (!m_currentScene->IsInitialized()) {
        m_currentScene->m_isInitialized = true;
        m_currentScene->OnCreate();
    }

    m_currentScene->m_isActive = true;
    m_currentScene->OnActivate();
    std::cout << "SceneManager: Switched to scene '" << name << "'" << std::endl;
}

void SceneManager::UpdateCurrentScene(float deltaTime) {
    if (m_currentScene && m_currentScene->IsActive()) {
        m_currentScene->Update(deltaTime);
    }
}

void SceneManager::RenderCurrentScene() {
    if (m_currentScene && m_currentScene->IsActive()) {
        m_currentScene->Render();
    }
}

std::shared_ptr<Scene> SceneManager::GetCurrentScene() const {
    return m_currentScene;
}

std::shared_ptr<Scene> SceneManager::GetScene(const std::string& name) {
    auto it_loaded = m_loadedScenes.find(name);
    if (it_loaded != m_loadedScenes.end()) {
        return it_loaded->second;
    }

    auto it_factory = m_sceneFactories.find(name);
    if (it_factory != m_sceneFactories.end()) {
        std::shared_ptr<Scene> scene = it_factory->second();
        if (scene) {
            m_loadedScenes[name] = scene;
            if (!scene->IsInitialized()) {
                scene->m_isInitialized = true;
                scene->OnCreate();
            }
            return scene;
        }
    }
    return nullptr;
}

void SceneManager::UnloadScene(const std::string& name) {
    auto it = m_loadedScenes.find(name);
    if (it != m_loadedScenes.end()) {
        std::shared_ptr<Scene> sceneToUnload = it->second;

        if (m_currentScene == sceneToUnload) {
            if (m_currentScene->IsActive()) {
                m_currentScene->m_isActive = false;
                m_currentScene->OnDeactivate();
            }
            m_currentScene = nullptr;
            m_currentSceneName = "";
        }
        
        if (sceneToUnload->IsInitialized()) {
            sceneToUnload->OnDestroy();
            sceneToUnload->m_isInitialized = false;
        }
        
        m_loadedScenes.erase(it);
        std::cout << "SceneManager: Unloaded scene '" << name << "'" << std::endl;
    }
}

void SceneManager::UnloadAllScenes() {
    if (m_currentScene && m_currentScene->IsActive()) {
        m_currentScene->m_isActive = false;
        m_currentScene->OnDeactivate();
    }
    m_currentScene = nullptr;
    m_currentSceneName = "";

    for (auto& pair : m_loadedScenes) {
        if (pair.second && pair.second->IsInitialized()) {
            pair.second->OnDestroy();
            pair.second->m_isInitialized = false;
        }
    }
    m_loadedScenes.clear();
    std::cout << "SceneManager: All scenes unloaded." << std::endl;
}

}
